package org.kunlong.qgen.service;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.kunlong.qgen.domain.AbstractQuestion;
import org.kunlong.qgen.domain.QuestionHolder;
import org.kunlong.qgen.domain.QuestionType;

public abstract class AbstractMultiThreadsQuestionLoadService implements
		QuestionLoadService {

	public void loadFromXML(List<File> files, QuestionHolder questionHolder) {
		ExecutorService executorService = Executors.newFixedThreadPool(4);
		CyclicBarrier barrier = new CyclicBarrier(5);
		Queue<File> questionFiles =new LinkedList<File>();
		//load all file to a queue
		for(File f:files){
			questionFiles.add(f);
		}
		Job[] jobs = new Job[4];
		for (Job j : jobs) {
			j = new Job(barrier, this, questionFiles, questionHolder);
			executorService.execute(j);
		}
		try {
			barrier.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
			System.exit(-1);
		} catch (BrokenBarrierException e) {
			System.exit(-1);
			e.printStackTrace();
		}
		System.out.println("Loading Finished!");
		System.out.println("Load Detail:");
		Set<Entry<QuestionType,List<AbstractQuestion>>> entrys=questionHolder.getMap().entrySet();
		for(Entry<QuestionType,List<AbstractQuestion>> entry:entrys){
			System.out.println("Question Type:"+entry.getKey().getName()+" Question Number:"+entry.getValue().size());
		}
		executorService.shutdown();
	}
	/**
	 * parse a question xml file
	 * */
	abstract public void parse(File file, QuestionHolder questionHolder)
			throws Exception;

	class Job implements Runnable {
		private CyclicBarrier cyclicBarrier;
		private AbstractMultiThreadsQuestionLoadService service;
		private Queue<File> fileList;
		private boolean status = true;
		private QuestionHolder questionHolder;

		public Job(CyclicBarrier cyclicBarrier,
				AbstractMultiThreadsQuestionLoadService service,
				Queue<File> fileList, QuestionHolder questionHolder) {
			this.service = service;
			this.cyclicBarrier = cyclicBarrier;
			this.fileList = fileList;
			this.questionHolder = questionHolder;
		}

		private boolean validateFile(File file) {
			return true;
		}

		public void run() {
			while (status) {
				File file = null;
				synchronized (fileList) {
					file = fileList.poll();
				}
				if (file == null) {
					// all the word has been done
					status = false;
				} else {
					if (validateFile(file)) {
						try {
							System.out.println("Phrase File:"+file.getName());
							service.parse(file, questionHolder);
						} catch (Exception e) {
							e.printStackTrace();
							System.out.println("Error Loading File:"
									+ file.getName());
						}
					}
				}
			}
			try {
				System.out.println("Waiting For Synchronized:"+Thread.currentThread().getId());
				cyclicBarrier.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			}
		}
	}
}
